#ifndef LOCALMAPPING_H
#define LOCALMAPPING_H

#include "KeyFrame.h"
#include "Map.h"

class Tracking;
class Map;
class LocalMapping
{
public:
	 LocalMapping(Map* pMap);

	 ~LocalMapping();

	// Main function
    void Run();

	void InsertKeyFrame(KeyFrame* pKF);

	// Thread Synch
	void RequestStop();

	void RequestReset();

	bool Stop();

	void Release();

	bool isStopped();

	bool stopRequested();

	bool AcceptKeyFrames();

	void SetAcceptKeyFrames(bool flag);

	bool SetNotStop(bool flag);

	void InterruptBA();

	void RequestFinish();

	bool isFinished();

	int KeyframesSize();

	bool CheckNewKeyFrames();

	void ProcessNewKeyFrame();

	void CreateNewMapPoints();

	cv::Mat ComputeF12(KeyFrame* &pKF1, KeyFrame* &pKF2);

	cv::Mat SkewSymmetricMatrix(const cv::Mat &v);

	int SearchForTriangulation(KeyFrame *pKF1, KeyFrame *pKF2, cv::Mat F12,
					std::vector<std::pair<size_t, size_t> > &vMatchedPairs);

	bool CheckDistEpipolarLine(const cv::KeyPoint &kp1,const cv::KeyPoint &kp2,const cv::Mat &F12,const KeyFrame* pKF2);

	void MapPointCulling();

	void SearchInNeighbors();
	
	int Fuse(KeyFrame *pKF, const std::vector<MapPoint *> &vpMapPoints, const float th=3.0);

	void KeyFrameCulling();

	void ResetIfRequested();

	bool CheckFinish();

	void SetFinish();

	int KeyframesInQueue();

	void LocalBundleAdjustment(KeyFrame *pKF, bool* pbStopFlag, Map* pMap);
protected:
	Map* m_Map;

	KeyFrame* m_CurrentKeyFrame;

	std::list<MapPoint*> m_listRecentAddedMapPoints;

	std::list<KeyFrame*> m_listNewKeyFrames;
	std::mutex m_MutexNewKFs;
	bool m_AbortBA;

	std::mutex m_MutexStop;
	bool m_StopRequested;
	bool m_NotStop;
	bool m_Stopped;

	bool m_ResetRequested;
    std::mutex m_MutexReset;


	bool m_FinishRequested;
	bool m_Finished;
	std::mutex m_MutexFinish;

	bool m_AcceptKeyFrames;
    std::mutex m_MutexAccept;
};
#endif  //LOCALMAPPING_H